﻿using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Legend.Object;

namespace Legend.Component.Common
{
    public class SimpleRenderable : Interface.IRenderable
    {
        private Model model = null;
        private VertexDeclaration vertexDecl = null;
        static private Texture shadowTexture = null;
        private VertexPositionTexture[] vertices;
        private int[] indices;
        private bool castShadow = true;
        private bool alphaBlend = false;
        private static EffectPool effectPool = new EffectPool();
        
        public Model Model
        {
            get { return model; }
            set 
            { 
                model = value;
                ResetShadowVertices();
            }
        }

        public bool CastShadow
        {
            get { return castShadow; }
            set { castShadow = value; }
        }

        public bool AlphaBlend
        {
            get { return alphaBlend; }
            set { alphaBlend = value; }
        }

        public SimpleRenderable()
        {
            vertices = new VertexPositionTexture[4];
            indices = new int[]{0, 1, 2, 3};
        }

        private void ResetShadowVertices()
        {
            BoundingBox boundingBox = Legend.Helper.Mesh.GetModelBoundingBox(model);

            vertices[0].Position.X = boundingBox.Max.X;
            vertices[0].Position.Y = boundingBox.Min.Y;
            vertices[0].Position.Z = 1f;
            vertices[0].TextureCoordinate.X = 1f;
            vertices[0].TextureCoordinate.Y = 1f;

            vertices[1].Position.X = boundingBox.Min.X;
            vertices[1].Position.Y = boundingBox.Min.Y;
            vertices[1].Position.Z = 1f;
            vertices[1].TextureCoordinate.X = 0;
            vertices[1].TextureCoordinate.Y = 1f;

            vertices[2].Position.X = boundingBox.Max.X;
            vertices[2].Position.Y = boundingBox.Max.Y;
            vertices[2].Position.Z = 1f;
            vertices[2].TextureCoordinate.X = 1f;
            vertices[2].TextureCoordinate.Y = 0;

            vertices[3].Position.X = boundingBox.Min.X;
            vertices[3].Position.Y = boundingBox.Max.Y;
            vertices[3].Position.Z = 1f;
            vertices[3].TextureCoordinate.X = 0;
            vertices[3].TextureCoordinate.Y = 0;
        }

        public void LoadModel(ContentManager contentManager, string name)
        {
            model = contentManager.Load<Model>(name);
            ResetShadowVertices();

            if (shadowTexture == null)
            {
                shadowTexture = contentManager.Load<Texture>("Shadow");
            }
        }
        
        public override void Render(GraphicsDevice device)
        {
            if (model == null)
            {
                return;
            }

            device.RenderState.DepthBufferEnable = true;

            if (alphaBlend)
            {
                device.RenderState.AlphaBlendEnable = true;
//                device.RenderState.AlphaTestEnable = true;
                device.RenderState.BlendFunction = BlendFunction.Add;
                device.RenderState.SourceBlend = Blend.One;
                device.RenderState.DestinationBlend = Blend.SourceAlpha;
            }
            else
            {
                device.RenderState.AlphaBlendEnable = false;
//                device.RenderState.AlphaTestEnable = false;
            }
            
            foreach (ModelMesh mesh in model.Meshes)
            {
                BasicEffect effect = mesh.Effects[0] as BasicEffect;

                effect.EnableDefaultLighting();
                effect.AmbientLightColor = AmbientColor;
                effect.View = ViewMatrix;
                effect.Projection = ProjectionMatrix;
                effect.World = WorldMatrix;
                
                mesh.Draw();

                if (castShadow)
                {
                    effect.Begin();

                    Matrix worldMatrix = Matrix.Identity;
                    worldMatrix.Translation = WorldMatrix.Translation;
                    vertices[0].Position.Z = vertices[1].Position.Z = vertices[2].Position.Z = vertices[3].Position.Z = worldMatrix.M43 * -1 + 1;

                    device.RenderState.AlphaBlendEnable = true;
                    device.RenderState.BlendFunction = BlendFunction.ReverseSubtract;
                    device.RenderState.SourceBlend = Blend.SourceAlpha;
                    device.RenderState.DestinationBlend = Blend.One;
                    device.Textures[0] = shadowTexture;
                    effect.World = worldMatrix;

                    if (vertexDecl == null || vertexDecl.GraphicsDevice != device)
                    {
                        vertexDecl = new VertexDeclaration(device, VertexPositionTexture.VertexElements);
                    }
                    device.VertexDeclaration = vertexDecl;
                    device.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices, 0, 4, indices, 0, 2);
                    device.RenderState.AlphaBlendEnable = false;
                    effect.End();
                }

                //Legend.Component.Interface.ICollision collision = Owner.FindComponent<Legend.Component.Interface.ICollision>();

                //if (collision != null)
                //{
                //    effect.Begin();
                //    device.VertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);

                //    BoundingBox boundingBox = collision.LocalBoundingBox;
                //    Vector3 t0 = new Vector3(boundingBox.Max.X, boundingBox.Max.Y, boundingBox.Max.Z);
                //    Vector3 t1 = new Vector3(boundingBox.Min.X, boundingBox.Max.Y, boundingBox.Max.Z);
                //    Vector3 t2 = new Vector3(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Max.Z);
                //    Vector3 t3 = new Vector3(boundingBox.Max.X, boundingBox.Min.Y, boundingBox.Max.Z);
                //    Vector3 b0 = new Vector3(boundingBox.Max.X, boundingBox.Max.Y, boundingBox.Min.Z);
                //    Vector3 b1 = new Vector3(boundingBox.Min.X, boundingBox.Max.Y, boundingBox.Min.Z);
                //    Vector3 b2 = new Vector3(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Min.Z);
                //    Vector3 b3 = new Vector3(boundingBox.Max.X, boundingBox.Min.Y, boundingBox.Min.Z);

                //    VertexPositionColor[] bb = new VertexPositionColor[] 
                //    { 
                //        new VertexPositionColor(t0, Color.Blue), 
                //        new VertexPositionColor(t1, Color.Blue),
                //        new VertexPositionColor(t1, Color.Blue),
                //        new VertexPositionColor(t2, Color.Blue),
                //        new VertexPositionColor(t2, Color.Blue),
                //        new VertexPositionColor(t3, Color.Blue),
                //        new VertexPositionColor(t3, Color.Blue),
                //        new VertexPositionColor(t0, Color.Blue),
                //        new VertexPositionColor(t0, Color.Blue),
                //        new VertexPositionColor(b0, Color.Blue),
                //        new VertexPositionColor(t1, Color.Blue),
                //        new VertexPositionColor(b1, Color.Blue),
                //        new VertexPositionColor(t2, Color.Blue),
                //        new VertexPositionColor(b2, Color.Blue),
                //        new VertexPositionColor(t3, Color.Blue),
                //        new VertexPositionColor(b3, Color.Blue),
                //        new VertexPositionColor(b0, Color.Blue),
                //        new VertexPositionColor(b1, Color.Blue),
                //        new VertexPositionColor(b1, Color.Blue),
                //        new VertexPositionColor(b2, Color.Blue),
                //        new VertexPositionColor(b2, Color.Blue),
                //        new VertexPositionColor(b3, Color.Blue),
                //        new VertexPositionColor(b3, Color.Blue),
                //        new VertexPositionColor(b0, Color.Blue) 
                //    };

                //    device.DrawUserPrimitives(PrimitiveType.LineList, bb, 0, 12);
                //    effect.End();
                //}
            }
            
            
            //collision.BoundingBox

            device.RenderState.AlphaBlendEnable = false;
//            device.RenderState.AlphaTestEnable = false;
        }
    }
}
